package com.yuan.chinesechess;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.yuan.piece.Cannon;
import com.yuan.piece.Elephant;
import com.yuan.piece.Guard;
import com.yuan.piece.Horse;
import com.yuan.piece.King;
import com.yuan.piece.PieceBase;
import com.yuan.piece.Soldier;
import com.yuan.piece.Veicle;
import com.yuan.util.Utils;
import com.yuan.web.Client;
import com.yuan.web.Server;

public class ChessMain extends JFrame {
        public static final int RED = 1;
        public static final int BLACK = 0;
        public static final int x = 9;
        public static final int y = 20;
        public static final int LEN = 41;
        public static final int WIDTH = 377;
        public static final int HEIGHT = 470;
        public static final int BORDERLEFT = 30;
        public static final int BORDERTOP = 38;
        public static final Dimension size = new Dimension(WIDTH, HEIGHT);
        private int side = RED;
        private PieceBase selected = null; //
        private Image bufferImage = null;
        private Graphics bufferScreen = null;
        private ChessPanel panel;
        private Map map;
        private King bKing;
        private King rKing;
        private LinkedList<PieceBase[][]> history;
        private JMenuItem item1;
        private JMenuItem item2;
        private JMenuItem item3;
        private JMenuItem item4;

        public ChessMain() {
                setTitle("chinses chess");
                setSize(WIDTH, HEIGHT);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                setResizable(false);
                setLocationRelativeTo(null);
                setLayout(new BorderLayout());
                Container c = getContentPane();
                panel = new ChessPanel();
                JMenuBar bar = new JMenuBar();
                JMenu menu = new JMenu("�˵�");
                JMenu option = new JMenu("����");
                item1 = new JMenuItem("双人");
                item2 = new JMenuItem("service");
                item3 = new JMenuItem("join");
                item4 = new JMenuItem("regret");
                menu.add(item2);
                menu.addSeparator();
                menu.add(item3);
                option.add(item1);
                option.addSeparator();
                option.add(item4);
                bar.add(menu);
                bar.add(option);
                c.add(panel, BorderLayout.CENTER);
                c.add(bar, BorderLayout.NORTH);

                // this.setIconImage(new ImageIcon("CANVAS.GIF").getImage());
                setVisible(true);
                init();
        }

        public void init() {
                bufferImage = createImage(WIDTH, HEIGHT);
                bufferScreen = bufferImage.getGraphics();
                initPiece();
                item1.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                // TODO Auto-generated method stub                              
                                initPiece();                            
                                drawMap();
                                repaint();
                        }              
                });
                
                item2.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                                try {
                                        //setVisible(false);
                                        new Server();
                                        
                                } catch (IOException e1) {
                                        // TODO Auto-generated catch block
                                        e1.printStackTrace();
                                }
                        }
                });
                
                item3.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                                String ip = JOptionPane.showInputDialog("Enter the ip:");
                                if (ip != null) {
                                        setVisible(false);
                                        new Client(ip,3301);
                                }                            
                        }
                });
                
                item4.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                // TODO Auto-generated method stub
                                //System.out.println(history.size());
                                if (history.size() >= 2) {                                 
                                        map.setMap(history.get(history.size() - 2));
                                        history.removeLast();
                                        side = side==RED?BLACK:RED;                                       
                                        drawMap();
                                        repaint();
                                }
                        }
                });

                addMouseListener(new MouseAdapter() {
                        public void mouseClicked(MouseEvent e) {
                                drawMap();
                                int x = e.getX();
                                int y = e.getY();
                                double xx = x / LEN;
                                double yy = (y - BORDERTOP) / LEN;
                                int i = new BigDecimal(xx).setScale(0,
                                                BigDecimal.ROUND_HALF_UP)
                                                .intValue();
                                int j = new BigDecimal(yy).setScale(0,
                                                BigDecimal.ROUND_HALF_UP)
                                                .intValue();
                                PieceBase piece = map.getValue(i, j);
                                if (piece != null) { // ѡ������
                                        if (piece.getType() == side) {
                                                selected = piece;
                                                piece.draw(bufferScreen,
                                                                piece.getSelectedImagePath());
                                        } else {
                                                if (selected != null) {
                                                        if (selected.move(map,
                                                                        i, j)) {
                                                      
                                                                historyStep(map);
                                                                side = side == RED ? BLACK
                                                                                : RED;
                                                                selected = null;
                                                                drawMap();
                                                        }
                                                }
                                        }
                                } else { // ѡ������
                                        if (selected != null) {
                                                if (selected.move(map, i, j)) {
                                                        historyStep(map);
                                                   
                                                        side = side == RED ? BLACK
                                                                        : RED;
                                                        selected = null;
                                                        drawMap();
                                                }
                                        }
                                }
                                repaint();
                                switch (isOver()) {
                                case 0:
                                        JOptionPane.showMessageDialog(
                                                        null,
                                                        "�ڷ���ʤ",
                                                        "alert",
                                                        JOptionPane.ERROR_MESSAGE);
                                        break;
                                case 1:
                                        JOptionPane.showMessageDialog(
                                                        null,
                                                        "�췽��ʤ",
                                                        "alert",
                                                        JOptionPane.ERROR_MESSAGE);
                                        break;
                                }
                        }
                });
                panel.repaint();
        }

        public void initPiece() {
                side = RED;
                map = new Map();
                history = new LinkedList<PieceBase[][]>();
                // ��
                Veicle bVeicleL = new Veicle(BLACK, 0, 0);
                Veicle bVeicleR = new Veicle(BLACK, 8, 0);
                Veicle rVeicleL = new Veicle(RED, 0, 9);
                Veicle rVeicleR = new Veicle(RED, 8, 9);
                map.setValue(bVeicleL, 0, 0);
                map.setValue(bVeicleR, 8, 0);
                map.setValue(rVeicleL, 0, 9);
                map.setValue(rVeicleR, 8, 9);

                // ��
                Horse bHorseL = new Horse(BLACK, 1, 0);
                Horse bHorseR = new Horse(BLACK, 7, 0);
                Horse rHorseL = new Horse(RED, 1, 9);
                Horse rHorseR = new Horse(RED, 7, 9);
                map.setValue(bHorseL, 1, 0);
                map.setValue(bHorseR, 7, 0);
                map.setValue(rHorseL, 1, 9);
                map.setValue(rHorseR, 7, 9);

                // ��
                Elephant bElephantL = new Elephant(BLACK, 2, 0);
                Elephant bElephantR = new Elephant(BLACK, 6, 0);
                Elephant rElephantL = new Elephant(RED, 2, 9);
                Elephant rElephantR = new Elephant(RED, 6, 9);
                map.setValue(bElephantL, 2, 0);
                map.setValue(bElephantR, 6, 0);
                map.setValue(rElephantL, 2, 9);
                map.setValue(rElephantR, 6, 9);
                // ʿ
                Guard bGuardL = new Guard(BLACK, 3, 0);
                Guard bGuardR = new Guard(BLACK, 5, 0);
                Guard rGuardL = new Guard(RED, 3, 9);
                Guard rGuardR = new Guard(RED, 5, 9);
                map.setValue(bGuardL, 3, 0);
                map.setValue(bGuardR, 5, 0);
                map.setValue(rGuardL, 3, 9);
                map.setValue(rGuardR, 5, 9);
                // ��˧
                bKing = new King(BLACK, 4, 0);
                rKing = new King(RED, 4, 9);
                map.setValue(bKing, 4, 0);
                map.setValue(rKing, 4, 9);
                // ʿ��
                Soldier bSoldier1 = new Soldier(BLACK, 0, 3);
                Soldier bSoldier2 = new Soldier(BLACK, 2, 3);
                Soldier bSoldier3 = new Soldier(BLACK, 4, 3);
                Soldier bSoldier4 = new Soldier(BLACK, 6, 3);
                Soldier bSoldier5 = new Soldier(BLACK, 8, 3);

                Soldier rSoldier1 = new Soldier(RED, 0, 6);
                Soldier rSoldier2 = new Soldier(RED, 2, 6);
                Soldier rSoldier3 = new Soldier(RED, 4, 6);
                Soldier rSoldier4 = new Soldier(RED, 6, 6);
                Soldier rSoldier5 = new Soldier(RED, 8, 6);
                map.setValue(bSoldier1, 0, 3);
                map.setValue(bSoldier2, 2, 3);
                map.setValue(bSoldier3, 4, 3);
                map.setValue(bSoldier4, 6, 3);
                map.setValue(bSoldier5, 8, 3);
                map.setValue(rSoldier1, 0, 6);
                map.setValue(rSoldier2, 2, 6);
                map.setValue(rSoldier3, 4, 6);
                map.setValue(rSoldier4, 6, 6);
                map.setValue(rSoldier5, 8, 6);
                // ��
                Cannon bCannonL = new Cannon(BLACK, 1, 2);
                Cannon bCannonR = new Cannon(BLACK, 7, 2);
                Cannon rCannonL = new Cannon(RED, 1, 7);
                Cannon rCannonR = new Cannon(RED, 7, 7);
                map.setValue(bCannonL, 1, 2);
                map.setValue(bCannonR, 7, 2);
                map.setValue(rCannonL, 1, 7);
                map.setValue(rCannonR, 7, 7);
                historyStep(map);
                drawMap();
        }
        
        public void historyStep(Map map) {
                PieceBase[][] p = new PieceBase[Map.x][Map.y];
                try {
                        for (int i = 0; i < Map.x; i++) {
                                for(int j =0; j < Map.y; j++ ) {
                                        PieceBase piece = map.getValue(i, j);
                                        if (piece != null) {
                                                p[i][j] = (PieceBase) piece.clone();
                                        } else {
                                                p[i][j] = null;
                                        }                                       
                                }
                        }
                } catch (CloneNotSupportedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                history.addLast(p);
        }

        public int isOver() {
                int winner = -1; // -1��ʾ��Ϸû����0��ʾ�ڷ���ʤ��1��ʾ�췽��ʤ
                outer: for (int i = 3; i <= 5; i++) { // �жϺ췽���Ƿ���
                        for (int j = 7; j <= 9; j++) {
                                if (map.getValue(i, j) instanceof King) {
                                        winner = -1;
                                        break outer;
                                } else {
                                        winner = 0;
                                }
                        }
                }
                if (winner == 0) {
                        return 0;
                } else if (winner == -1) {
                        outer: for (int i = 3; i <= 5; i++) { // �жϺڷ����Ƿ���
                                for (int j = 0; j <= 2; j++) {
                                        if (map.getValue(i, j) instanceof King) {
                                                winner = -1;
                                                break outer;
                                        } else {
                                                winner = 1;
                                        }
                                }
                        }
                }
                return winner;
        }

        public void drawMap() {
                bufferScreen.setColor(Color.WHITE);
                bufferScreen.fillRect(0, 0, WIDTH, HEIGHT);
                bufferScreen.drawImage(
                                new ImageIcon("res/CANVAS.GIF").getImage(), 0,
                                0, null);
                panel.setImg(bufferImage);

                for (int i = 0; i < Map.x; i++) {
                        for (int j = 0; j < Map.y; j++) {
                                PieceBase piece = map.getValue(i, j);
                                if (piece != null) {
                                        piece.draw(bufferScreen,
                                                piece.getImagePath());
                                }
                        }
                }
        }

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                new ChessMain();
        }
}